﻿#region Copyright (c) 2008 plexBB Team
/*  Copyright (c) 2008 plexBB Team
 *  
 *  This file is free software: you may copy, redistribute and/or modify it  
 *  under the terms of the GNU General Public License as published by the  
 *  Free Software Foundation, either version 2 of the License, or (at your  
 *  option) any later version.  
 *  
 *  This file is distributed in the hope that it will be useful, but  
 *  WITHOUT ANY WARRANTY; without even the implied warranty of  
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
 *  General Public License for more details.  
 *  
 *  You should have received a copy of the GNU General Public License  
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 */
#endregion

using System;
using System.CodeDom;
using System.Web.Compilation;
using System.Web.UI;
using PlexBB.Controls;

namespace PlexBB
{
    /// <summary>
    /// Lang:LANG_ITEM_KEY*:format
    /// * - optional, means that blank result should be returned if language item returns empty value
    /// format - optional, used within string.Format(xxx) function to format lang value
    /// </summary>
    [ExpressionPrefix("Lang")]
    public class LangExpressionBuilder : ExpressionBuilder
    {
        public static string FormatBlankIfEmpty(string format, string value)
        {
            return value.Length > 0 ? string.Format(format, value) : string.Empty;
        }

        public override object EvaluateExpression(object target, BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
        {
            ParsedData data = (ParsedData)parsedData;
            string langItem = ((ForumControl)context.TemplateControl).Lang[data.LangKey];
            if (data.Format == null)
            {
                return langItem;
            }
            else if (data.BlankIfEmpty)
            {
                return FormatBlankIfEmpty(data.Format, langItem);
            }
            else
            {
                return string.Format(data.Format, langItem);
            }
        }

        public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
        {
            ParsedData data = (ParsedData)parsedData;

            CodeExpression langItem = new CodeIndexerExpression(
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Lang"),
                new CodePrimitiveExpression(data.LangKey));

            if (data.Format == null)
            {
                // this.Lang["xxx"]
                return langItem;
            }
            else if (data.BlankIfEmpty)
            {
                // LangExpressionBuilder.FormatBlankIfEmpty(this.Lang["xxx"], "FORMAT")
                return new CodeMethodInvokeExpression(
                       new CodeTypeReferenceExpression(GetType()),
                       "FormatBlankIfEmpty",
                       new CodePrimitiveExpression(data.Format),
                       langItem);
            }
            else
            {
                // else return simple string.Format(...)
                return new CodeMethodInvokeExpression(
                    new CodeTypeReferenceExpression(typeof(string)),
                    "Format",
                    new CodePrimitiveExpression(data.Format),
                    langItem);
            }
        }

        public override object ParseExpression(string expression, Type propertyType, ExpressionBuilderContext context)
        {
            // create and return ParsedData object
            string[] items = expression.Split(new[] { ':' }, 2);
            ParsedData data= new ParsedData();
            if (items.Length > 1)
            {
                data.Format = items[1];
            }
            string item0 = items[0];
            data.BlankIfEmpty = item0.EndsWith("*");
            data.LangKey = data.BlankIfEmpty ? item0.Substring(0, item0.Length - 1) : item0;
            return data;
        }

        public override bool SupportsEvaluate
        {
            get { return true; }
        }

        private class ParsedData
        {
            public string LangKey;
            public string Format;
            public bool BlankIfEmpty;
        }
    }
}
